import java.util.*;

public class Snake {
    // 画布大小
    static public final int ROW = 15;
    static public final int COL = 30;

    // 方向键定义
    static public final char UP = 'w';
    static public final char DOWN = 's';
    static public final char LEFT = 'a';
    static public final char RIGHT = 'd';

    // 蛇身最大长度
    static public final int SMAX = 100;

    // 画布数组
    static public char bg[][] = new char[ROW][COL];
    static public char bgCh = '#';
    // 蛇头信息
    static public int x = 3, y = 3, snakeColor = 31;
    static public char direct = RIGHT, snakeCh = '@';
    // 蛇身信息
    static public int snakeX[] = new int[SMAX];
    static public int snakeY[] = new int[SMAX];
    static public int snakeLen = 0, bodyColor = 33;
    static public char bodyCh = '*';
    // 食物信息
    static public int foodX = 0, foodY = 0, foodColor = 32;
    static public char foodCh = 'F';
    // 定时器对象
    static public Timer t = new Timer();

    static public int ms = 300;

    static public void p(String format, Object ... obj) {
        System.out.printf(format, obj);
    }

    static public void init() {
        int i, j;
        for (i = 0; i < ROW; ++i) {
            for (j = 0; j < COL; ++j) {
                if (j == 0 || i == 0 || i == ROW - 1 || j == COL - 1)
                    bg[i][j] = bgCh;
                else
                    bg[i][j] = ' ';
            }
        }
    }

    static public void draw() {
        // 画蛇身
        for (int i = 0; i < snakeLen; ++i) {
            bg[snakeX[i]][snakeY[i]] = bodyCh;
        }
        // 画食物
        bg[foodX][foodY] = foodCh;
        // 画蛇头
        bg[x][y] = snakeCh;
    }


    //检测食物随机坐标是否合法(不能随机到蛇头和蛇身上)
    static public boolean checkXY(int foodX, int foodY) {
        if (foodX == x && foodY == y)
            return false;

        for (int i = 0; i < snakeLen; ++i) {
            if (foodX == snakeX[i] && foodY == snakeY[i]) {
                return false;
            }
        }
        return true;
    }

    // 新食物随机坐标
    static public void randFood() {
        while (true) {
            foodX = Kyo.rand(1, ROW - 2);
            foodY = Kyo.rand(1, COL - 2);
            if (checkXY(foodX, foodY))
                break;
        }
        snakeColor = foodColor;
        foodColor = Kyo.rand(30, 36);
    }

    // 吃食物动作
    static public void eatFood() {
        snakeX[snakeLen] = foodX;
        snakeY[snakeLen] = foodY;
        snakeLen++;
        randFood();
        ms -= 100;
        if (ms == 0)
            ms = 500;
        setTimer();
    }

    static public int move() {
        int i;

        //检测蛇头是否碰墙
        if (x == ROW - 1 || x == 0 || y == COL - 1 || y == 0) {
            snakeExit();
        }

        // 检测蛇头与蛇身是否相碰
        for (i = 0; i < snakeLen; ++i) {
            if (snakeX[i] == x && snakeY[i] == y)
                snakeExit();
        }

        if (foodX == x && foodY == y) {
            eatFood();
        }

        int sx = x, sy = y;

        switch (direct) {
            case UP:
                x--;
                break;
            case DOWN:
                x++;
                break;
            case LEFT:
                y--;
                break;
            case RIGHT:
                y++;
                break;
        }

        for (i = snakeLen - 1; i > 0; --i) {
            snakeX[i] = snakeX[i - 1];
            snakeY[i] = snakeY[i - 1];
        }
        snakeX[0] = sx;
        snakeY[0] = sy;

        return 0;
    }

    static public void show() {
        int i, j;

        Vt.gotoxy(1, 1);
        for (i = 0; i < ROW; ++i) {
            for (j = 0; j < COL; ++j) {
                if (bg[i][j] == snakeCh)
                    Vt.out("".valueOf(bg[i][j]), snakeColor);
                else if (bg[i][j] == foodCh)
                    Vt.out("".valueOf(bg[i][j]), foodColor);
                else if (bg[i][j] == bodyCh)
                    Vt.out("".valueOf(bg[i][j]), bodyColor);
                else
                    System.out.printf("%c", bg[i][j]);
            }
            System.out.printf("\n");
        }
    }

    static public void snakeInit() {
        //清屏和隐藏
        Vt.cmd(Vt.SCREEN).cmd(Vt.HIDE);
        // 终端输入初始化, 终端配置无缓冲输入 关闭回显
        Kyo.init();
        // 首次食物坐标随机
        randFood();
    }

    static public void snakeExit() {
        // 最后显示一次画布
        show();
        // 关闭定时器
        t.cancel();
        // 终端配置还原 开启回显
        Kyo.exit();
        // 显示光标和定位画布下面
        Vt.cmd(Vt.SHOW).gotoxy(ROW + 1, 1);
        // 退出程序
        System.exit(0);
    }

    static public void setTimer() {
        t.cancel();
        t = new Timer();
        t.schedule(new TimerTask() {
            public void run() {
                init();
                draw();
                move();
                show();
            }
        }, ms, ms);
    }

    static public boolean keyHandle(int key) {
        switch (key) {
            case 27:
                return true;
            case UP:
                if (direct != DOWN)
                    direct = UP;
                break;
            case DOWN:
                if (direct != UP)
                    direct = DOWN;
                break;
            case LEFT:
                if (direct != RIGHT)
                    direct = LEFT;
                break;
            case RIGHT:
                if (direct != LEFT)
                    direct = RIGHT;
                break;
            default:
                break;
        }
        return false;
    }

    static public void main(String [] args) {
        snakeInit();

        setTimer();

        while (true) {
            if (keyHandle(Kyo.key())) {
                break;
            }
        }
        snakeExit();
    }
}
